﻿using System;

namespace _16_面向对象___类与对象
{
    class Program
    {
        static void Main(string[] args)
        {
            //什么是类？
            // class 关键字声明的一个结构 ，用 花括号囊括
            // 上面的 Program 就是一个类型
            // 对象：类型的 实例  （约定 ：形如 new Program 的过程就是实例化，得到的结果就是对象）
            //  类型 其实就是一个模板，对象可以 new 多个，但模板只需一个


            //1. 分别创建 冰箱 和 大象 的对象（实例）
            Fridge fridge = new Fridge();
            fridge.name = "新飞冰箱";
            fridge.size = 100;
            fridge.内容物 = null;

            Elephant elephant = new Elephant();
            elephant.name = "云南大象A";
            elephant.size = 100;
            elephant.age = 2;

            //2. 开冰箱门
            fridge.OpenDoor();
            fridge.FillObject(elephant, elephant.size);
            //3. 大象怎么配合进冰箱
            elephant.Walk(fridge.name, fridge.size);
            //4.  关冰箱门
            fridge.CloseDoor();

            // 5. 有人关心冰箱里面都有啥
            if (fridge.内容物 is Elephant ele)
            {
                Console.WriteLine($"天啦，有人把大象丢在了 {fridge.name} 冰箱，{ele.name} 太惨了！");
            }

            //6. 情景：门关了，你还要放东西
            Elephant elephant2 = new Elephant();
            elephant2.name = "云南大象B";
            elephant2.size = 200;
            elephant2.age = 2;
            fridge.FillObject(elephant2);

            //7. 情景：门开了，但是冰箱放不下了
            Console.WriteLine("------7. 情景：门开了，但是冰箱放不下了----------");
            fridge.OpenDoor();
            fridge.FillObject(elephant2);
            fridge.CloseDoor();

            //8. 情景：给你腾位置
            Console.WriteLine("------ 8. 情景：给你腾位置 ----------");
            fridge.内容物 = null;
            fridge.OpenDoor();
            fridge.FillObject(elephant2, elephant2.size);
            fridge.CloseDoor();
            if (fridge.内容物 is Elephant ele1)
            {
                Console.WriteLine($"天啦，有人把大象丢在了 {fridge.name} 冰箱，{ele1.name} 太惨了！");
            }

            Person person = new Person();
            //person.BloodType = "B";
            Console.WriteLine($"你叫 {person.Name} - 血型是：{person.BloodType}");
            person.Name = "中国人";
        }
    }

    /// <summary>
    /// 性别
    /// </summary>
    enum Sex
    {
        /// <summary>
        /// 男人
        /// </summary>
        Man,
        /// <summary>
        /// 女人
        /// </summary>
        Woman,
        /// <summary>
        /// 其他
        /// </summary>
        Other
    }

    // Person : 人 
    // 我们在程序世界里构建了一个人
    // 我们创建 Person 的过程，就是构建一个 对象 模板的过程，是面向对象的 第一站：我们把程序的世界和真实的世界用代码的形式连接在了一起
    // 我们用代码构建了世界：一个个对象构建的世界，这些对象可以与真实的世界产生一一对应的关联。
    // 我们现在写代码的思路就是面向对象了。
    //  程序人都这么说： 万物皆对象
    //  万物：真实世界的事物（普罗大众的宏观世界） ，对于程序构建的世界里面的事物（程序人的宏观世界）
    //  皆对象： 都是对象， 真实世界的事物是对象，从真实世界抽象出来的特性构成的程序世界的事物，也是对象。
    //  抽象： 一个大概的东西，你描述的只是你目前关心的或者你的认识范围能够理解的东西。


    /// <summary>
    /// 人
    /// </summary>
    class Person
    {
        // 概念性的，需要强记 ，同时也可以跟现实中的人进行类比
        //Person 的成员，成员又包括：字段、属性、方法（能力、行为）
        // 函数 = 方法 

        // 字段
        private int age; //年龄
        public Sex sex; //性别

        // 属性 ： 可以提供对赋值进行判断和限定
        // 约定：字段对内，属性对外
        // 变量名称规则：约定只要是属性，以大写字母开头
        //  get ： 获得
        // set : 设置
        // return : 返回
        // value : 值 （根据声明的数据类型不同而不同）
        // 如果不是自动属性，就需要配合字段，例如本示例
        public int Age
        {
            get
            {
                return age;
            }
            set
            {
                if (value < 0)
                {
                    Console.WriteLine($"输入的年龄有点诡异，重置为 0 ");
                    value = 0;
                }
                else if (value > 200)
                {
                    Console.WriteLine($"输入的年龄好像有点大的离谱！");
                    value = 120;
                }
                age = value; //把年纪拿捏的死死的
            }
        }
        public string Name { get; set; } = "地球人"; //可读可写

        /// <summary>
        /// 血型 ： A、 B、 ab、 O、 熊猫血 ...
        /// <remarks>因为血型由基因决定，一出生就固定不可修改，所以是 只读 属性</remarks>
        /// </summary>
        public string BloodType { get; private set; } = "A";

        /// <summary>
        /// 记忆
        /// <para>记忆可以通过一起经历一些事情而写入他人的记忆中，但是他人的记忆你却不能读取，也就是只写 属性</para>
        /// 
        /// </summary>
        public string Memory { set; private get; } = "空白";


        /// <summary>
        /// 吃
        /// </summary>
        /// <param name="food">食物</param>
        public void Eat(string food)
        {
            // 可以丰富自己的逻辑：比如喜欢吃，不喜欢吃，可以在这里过滤
            Console.WriteLine($"{Name} 吃了 {food}");
        }

        /// <summary>
        /// 睡觉
        /// </summary>
        public void Sleep()
        {
            Console.WriteLine($"{Name} 在睡觉");
        }



        public void 生殖()
        {
            switch (sex)
            {
                case Sex.Man:
                    Console.WriteLine($"{Name} 是男人，不能生娃");
                    break;
                case Sex.Woman:
                    Console.WriteLine($"{Name} 是女，可以生猴子");
                    break;
                case Sex.Other:
                    Console.WriteLine($"{Name} 有点不对劲");
                    break;
                default:
                    Console.WriteLine($"{Name} 性别未知");
                    break;
            }
        }
    }

    /// <summary>
    /// 书
    /// </summary>
    class Book
    {
        public string 书名; //书名
        public DateTime 出版日期; // 出版日期
        public string 作者;
    }

    /// <summary>
    /// 电脑
    /// </summary>
    class Compute
    {
        /// <summary>
        /// 品牌型号
        /// </summary>
        public string name;
        /// <summary>
        /// 搭载的操作系统
        /// </summary>
        public string os;
        /// <summary>
        /// 中央处理器：CPU
        /// </summary>
        public string cpu;

        /// <summary>
        /// 看视频
        /// </summary>
        public void SeeVideo()
        {

        }
        /// <summary>
        /// 打游戏
        /// </summary>
        public void PlayGame()
        {

        }
    }

    //题目：我要把大象装进冰箱，在程序世界里面怎么用面向对象来描述：
    // 1. 冰箱的对象要有
    // 2.  存在一个大象
    // 3. 冰箱要有这个能力：装东西
    // 4.  冰箱容量贼拉大。 
    // 5. 大象体积、行为（走路）

    /// <summary>
    /// 冰箱
    /// </summary>
    class Fridge
    {
        /// <summary>
        /// 冰箱的容器
        /// </summary>
        public int size;

        /// <summary>
        /// 冰箱的名称：海尔冰箱
        /// </summary>
        public string name;

        public object 内容物; //冰箱里面装的东西

        /// <summary>
        ///  门打开了吗？
        ///  
        /// </summary>
        private bool isDoorOpened = false;


        /// <summary>
        /// 开门的能力
        /// </summary>
        public void OpenDoor()
        {
            isDoorOpened = true;
        }

        /// <summary>
        /// 开门的能力
        /// </summary>
        public void CloseDoor()
        {
            isDoorOpened = false;
        }

        /// <summary>
        /// 装东西
        /// fill ：装填的意思
        /// object ： 事物
        /// </summary>
        public void FillObject(object 要装的东西, int 尺寸 = 80)
        {
            if (isDoorOpened)
            {
                if (内容物 != null)
                {
                    Console.WriteLine($"{name} 里面有东西了，放不了了");
                    return;
                }
                if (size >= 尺寸)
                {
                    内容物 = 要装的东西;
                }
                else
                {
                    Console.WriteLine($"{name} 容量不够啊，放不了了");
                }
            }
            else
            {
                Console.WriteLine("大佬，咱们没开呢，放不了，放不了");
            }
        }

    }

    /// <summary>
    /// 大象
    /// </summary>
    class Elephant
    {
        /// <summary>
        /// 名称 ：云南大象
        /// </summary>
        public string name;
        /// <summary>
        /// 体积
        /// </summary>
        public int size;
        public int age;

        /// <summary>
        /// 行走
        /// </summary>
        public void Walk(string 目的地, int 空间)
        {
            if (空间 < size)
            {
                Console.WriteLine("对不起，进不去，太小了，好难受！！！");
            }
            Console.WriteLine($"{name} - 走到 {目的地}");
        }
    }



}
